package br.com.mensageiro.apresentacao.managedbean;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.faces.event.ActionEvent;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;

import org.primefaces.context.RequestContext;
import org.primefaces.event.FileUploadEvent;
import org.primefaces.model.DefaultStreamedContent;
import org.primefaces.model.DualListModel;
import org.primefaces.model.StreamedContent;
import org.primefaces.model.UploadedFile;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import br.com.mensageiro.apresentacao.mensagens.MensagemJSF;
import br.com.mensageiro.negocio.dao.GrupoDAO;
import br.com.mensageiro.negocio.dao.MensagemDestinatarioDAO;
import br.com.mensageiro.negocio.dao.UsuarioDAO;
import br.com.mensageiro.negocio.entidade.Arquivo;
import br.com.mensageiro.negocio.entidade.Grupo;
import br.com.mensageiro.negocio.entidade.GrupoUsuario;
import br.com.mensageiro.negocio.entidade.Mensagem;
import br.com.mensageiro.negocio.entidade.MensagemDestinatario;
import br.com.mensageiro.negocio.entidade.Usuario;
import br.com.mensageiro.negocio.servico.IGenericService;
import br.com.mensageiro.negocio.servico.IMensagemDestinatarioService;
import br.com.mensageiro.negocio.servico.IMensagemService;
import br.com.mensageiro.negocio.servico.IUsuarioService;
import br.com.mensageiro.utils.ArquivoUtils;

@Component
@Scope("session")
public class MensagemMB extends GenericManagedBeanCRUD<Mensagem> {
	@Autowired
	private IMensagemService mensagemService;
	@Autowired
	private IMensagemDestinatarioService mensagemDestinatarioService;
	@Autowired
	private IUsuarioService usuarioService;
	@Autowired
	private UsuarioDAO usuarioDAO;
	@Autowired
	private MensagemJSF addMensagem;
	@Autowired
	private ArquivoUtils arquivoUtils;
	@Autowired
	private MensagemDestinatarioDAO mensagemDestinatarioDAO;
	@Autowired
	private GrupoDAO grupoDAO;

	private Mensagem mensagem;
	private MensagemDestinatario mensagemDestinatario;

	@SuppressWarnings("rawtypes")
	private DataModel dmListaMensagensEnviadas;
	@SuppressWarnings("rawtypes")
	private DataModel dmListaMensagensRecebidas;
	protected RequestContext context;

	private String parametro = "entrada";
	private String nome = "";
	private String assunto = "";
	private Date data = null;
	private String indice;

	private DualListModel<Usuario> dualListUsuarios = new DualListModel<Usuario>();
	private DualListModel<Grupo> dualListGrupos = new DualListModel<Grupo>();

	protected List<Usuario> usuarioSource = new ArrayList<Usuario>();
	protected List<Usuario> usuarioTarget = new ArrayList<Usuario>();

	protected List<Grupo> grupoSource = new ArrayList<Grupo>();
	protected List<Grupo> grupoTarget = new ArrayList<Grupo>();

	private File arquivoSelecionado;

	List<StreamedContent> files;

	private List<File> listaArquivos = new ArrayList<File>();
	private List<String> caminho = new ArrayList<String>();

	public void visualisarMensagemEnviada(ActionEvent actionEvent) throws Exception {
		Mensagem m = new Mensagem();
		m = (Mensagem) dmListaMensagensEnviadas.getRowData();
		mensagem = mensagemService.getMensagem(m.getId());
		files = new ArrayList<StreamedContent>();

		for (Arquivo arquivo : mensagem.getArquivos()) {
			FileInputStream stream = new FileInputStream(arquivoUtils.byteTofile(arquivo.getArquivo(), arquivo.getNome()));
			StreamedContent sc = new DefaultStreamedContent(stream, "application/force-download", arquivo.getNome());
			files.add(sc);
		}
	}

	public void visualisarMensagemRecebida(ActionEvent actionEvent) throws Exception {
		context = RequestContext.getCurrentInstance();
		mensagemDestinatario = (MensagemDestinatario) dmListaMensagensRecebidas.getRowData();

		if (mensagemDestinatario.getStatus().equals("naolido")) {
			context.execute("cDialogAviso.show()");
		}
		files = new ArrayList<StreamedContent>();

		for (Arquivo arquivo : mensagemDestinatario.getMensagem().getArquivos()) {
			FileInputStream stream = new FileInputStream(arquivoUtils.byteTofile(arquivo.getArquivo(), arquivo.getNome()));
			StreamedContent sc = new DefaultStreamedContent(stream, "application/force-download", arquivo.getNome());
			files.add(sc);
		}
	}

	public void mudarStatusLeitura(ActionEvent actionEvent) throws Exception {
		MensagemDestinatario destinatario = new MensagemDestinatario();
		destinatario = mensagemDestinatarioDAO.doGet(mensagemDestinatario.getId());
		destinatario.setStatus("lido");
		destinatario.setDtconfirmacao(new Date());

		mensagemDestinatarioService.alterar(destinatario);
		dmListaMensagensEnviadas = null;
	}

	public void enviarMensagem(ActionEvent event) throws Exception {
		context = RequestContext.getCurrentInstance();
		try {
			mensagem.setMensagemDestinatarios(buildDestinatarios(mensagem));

			// mensagem.setMensagemDestinatarios(montaListaUsuarios(mensagem));
			// mensagem.setMensagemDestinatarios(montarListaUsuariosGrupos(mensagem));

			mensagem.setArquivos(montaListaArquivos(mensagem));

			mensagemService.inserir(mensagem);

			addMensagem.addInfo("Mensagem enviada com sucesso!");
			context.execute("escreverDialog.hide()");
		} catch (Exception e) {
			e.printStackTrace();
			addMensagem.addFatal("Erro ao enviar a mensagem!!");
		}
		dmListaMensagensEnviadas = null;

	}

	public void removerArquivoUpload() {
		context = RequestContext.getCurrentInstance();
		listaArquivos.remove(arquivoSelecionado);
		context.update(":formAnexo:dtListaAnexos");
	}

	public void renderizarDatatables() {
		mensagemDestinatario = new MensagemDestinatario();
		mensagem = new Mensagem();
		files = new ArrayList<StreamedContent>();
	}

	public void manipularFileUpload(FileUploadEvent event) {
		try {
			UploadedFile uploadedFile = event.getFile();
			InputStream in = new BufferedInputStream(uploadedFile.getInputstream());
			File arquivo = new File("C:\\Users\\Robson\\Documents\\" + uploadedFile.getFileName());
			FileOutputStream fout = new FileOutputStream(arquivo);
			while (in.available() != 0) {
				fout.write(in.read());
			}
			fout.close();
			listaArquivos.add(arquivo);
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public List<Arquivo> montaListaArquivos(Mensagem mensagem) {
		List<Arquivo> arquivos = new ArrayList<Arquivo>();
		for (File file : listaArquivos) {
			Arquivo arquivo = new Arquivo();
			arquivo.setArquivo(arquivoUtils.fileTobyte(file));
			arquivo.setNome(file.getName());
			arquivo.setMensagem(mensagem);
			arquivos.add(arquivo);
		}
		return arquivos;
	}

	public List<MensagemDestinatario> buildDestinatarios(Mensagem mensagem) {
		List<MensagemDestinatario> destUsuario = new ArrayList<MensagemDestinatario>();
		List<MensagemDestinatario> destGrupo = new ArrayList<MensagemDestinatario>();
		List<MensagemDestinatario> build = new ArrayList<MensagemDestinatario>();

		destUsuario = montarListaUsuariosGrupos(mensagem);
		destGrupo = montaListaUsuarios(mensagem);

//		for (MensagemDestinatario destinatario : destUsuario) {
//			for (MensagemDestinatario sourcegrupo : destGrupo) {
//				if (sourcegrupo.getId() == destinatario.getId()) {
//					destGrupo.remove(sourcegrupo);
//				}
//			}
//		}

		for (MensagemDestinatario destinatario : destGrupo) {
			build.add(destinatario);
		}

		for (MensagemDestinatario destinatario : destUsuario) {
			build.add(destinatario);
		}

		return build;
	}

	public List<MensagemDestinatario> montaListaUsuarios(Mensagem mensagem) {
		List<MensagemDestinatario> listaDestinatarios = new ArrayList<MensagemDestinatario>();

		if (dualListUsuarios.getTarget().size() > 0) {
			usuarioTarget = dualListUsuarios.getTarget();
		}

		for (int i = 0; i < usuarioTarget.size(); i++) {
			MensagemDestinatario destinatario = new MensagemDestinatario();
			Usuario usuario = new Usuario();
			usuario = usuarioDAO.doGet(Long.valueOf(String.valueOf(usuarioTarget.get(i))));
			destinatario.setUsuario(usuario);
			destinatario.setMensagem(mensagem);
			destinatario.setStatus("naolido");
			listaDestinatarios.add(destinatario);
		}
		return listaDestinatarios;
	}

	public List<MensagemDestinatario> montarListaUsuariosGrupos(Mensagem mensagem) {
		List<MensagemDestinatario> listaDestinatarios = new ArrayList<MensagemDestinatario>();
		List<Usuario> listUsuario = new ArrayList<Usuario>();

		if (dualListGrupos.getTarget().size() > 0) {
			grupoTarget = dualListGrupos.getTarget();
		}

		for (int i = 0; i < grupoTarget.size(); i++) {
			Grupo grupo = new Grupo();
			grupo = grupoDAO.doGetLong(Integer.parseInt(String.valueOf(grupoTarget.get(i))));
			for (GrupoUsuario grupoUsuario : grupo.getGrupoUsuarios()) {
				listUsuario.add(grupoUsuario.getUsuario());
			}
		}

		for (Usuario usuario : listUsuario) {
			MensagemDestinatario destinatario = new MensagemDestinatario();
			destinatario.setUsuario(usuario);
			destinatario.setMensagem(mensagem);
			destinatario.setStatus("naolido");
			listaDestinatarios.add(destinatario);
		}

		return listaDestinatarios;
	}

	public void prepararResponderMensagem() {
		usuarioSource = new ArrayList<Usuario>();
		usuarioTarget = new ArrayList<Usuario>();

		String usuario = String.valueOf(mensagemDestinatario.getUsuario().getId());

		// usuarioTarget.add(usuario);

		mensagem = new Mensagem();
		mensagem.setIdpai(mensagemDestinatario.getMensagem().getId());
	}

	public void prepararEnviarMensagem() {
		usuarioSource = new ArrayList<Usuario>();
		usuarioTarget = new ArrayList<Usuario>();

		mensagem = new Mensagem();
		listaArquivos = new ArrayList<File>();
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public DataModel getDmListaMensagensEnviadas() throws Exception {
		if (dmListaMensagensEnviadas == null) {
			dmListaMensagensEnviadas = new ListDataModel(mensagemService.listaMensagensUsuarioEnviadas());
		}
		return dmListaMensagensEnviadas;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public DataModel getDmListaMensagensRecebidas() throws Exception {
		dmListaMensagensRecebidas = new ListDataModel(mensagemDestinatarioService.listaMensagensUsuarioRecebidas(nome, assunto, data));
		return dmListaMensagensRecebidas;
	}

	public void limparDados() {
		nome = "";
		assunto = "";
		data = null;
		dmListaMensagensEnviadas = null;
	}

	public void limpaArquivos() {
		listaArquivos = new ArrayList<File>();
	}

	public MensagemMB(Class<Mensagem> classBean) {
		super(classBean);
	}

	@Override
	public IGenericService<Mensagem> getService() {
		return mensagemService;
	}

	public MensagemMB() {
		super(Mensagem.class);
	}

	public Mensagem getMensagem() {
		return mensagem;
	}

	public void setMensagem(Mensagem mensagem) {
		this.mensagem = mensagem;
	}

	public void setParametro(String parametro) {
		this.parametro = parametro;
	}

	public String getParametro() {
		return parametro;
	}

	public List<File> getListaArquivos() {
		return listaArquivos;
	}

	public void setListaArquivos(List<File> listaArquivos) {
		this.listaArquivos = listaArquivos;
	}

	public List<String> getCaminho() {
		return caminho;
	}

	public void setCaminho(List<String> caminho) {
		this.caminho = caminho;
	}

	public MensagemDestinatario getMensagemDestinatario() {
		return mensagemDestinatario;
	}

	public void setMensagemDestinatario(MensagemDestinatario mensagemDestinatario) {
		this.mensagemDestinatario = mensagemDestinatario;
	}

	@Override
	public Mensagem getBean() {
		return super.getBean();
	}

	public List<StreamedContent> getFiles() {
		return files;
	}

	public void setFiles(List<StreamedContent> files) {
		this.files = files;
	}

	public String getNome() {
		return nome;
	}

	public void setNome(String nome) {
		this.nome = nome;
	}

	public String getAssunto() {
		return assunto;
	}

	public void setAssunto(String assunto) {
		this.assunto = assunto;
	}

	public Date getData() {
		return data;
	}

	public void setData(Date data) {
		this.data = data;
	}

	public String getIndice() {
		return indice;
	}

	public void setIndice(String indice) {
		this.indice = indice;
	}

	public File getArquivoSelecionado() {
		return arquivoSelecionado;
	}

	public void setArquivoSelecionado(File arquivoSelecionado) {
		this.arquivoSelecionado = arquivoSelecionado;
	}

	public DualListModel<Usuario> getDualListUsuarios() {
		dualListUsuarios = new DualListModel<Usuario>();

		usuarioSource = usuarioService.getListaUsuariosRamais();
		dualListUsuarios = new DualListModel<Usuario>(usuarioSource, usuarioTarget);
		return dualListUsuarios;
	}

	public void setDualListUsuarios(DualListModel<Usuario> dualListUsuarios) {
		this.dualListUsuarios = dualListUsuarios;
	}

	public DualListModel<Grupo> getDualListGrupos() {
		dualListGrupos = new DualListModel<Grupo>();

		grupoSource = grupoDAO.getListaGrupos();
		dualListGrupos = new DualListModel<Grupo>(grupoSource, grupoTarget);
		return dualListGrupos;
	}

	public void setDualListGrupos(DualListModel<Grupo> dualListGrupos) {
		this.dualListGrupos = dualListGrupos;
	}

}
